ext.define('extension.gui', function() {

var utils = extension.utils;

var Highlighter = {
    open: function() {
        if (!this.isOpen()) {
            this.canvas.width = window.innerWidth;
            this.canvas.height = window.innerHeight;
            this.parent.appendChild(this.host);
            this.parent.addEventListener('keyup', this, true);
        }
    },
    isOpen: function() {
        return this.parent.contains(this.host);
    },
    close: function() {
        if (this.isOpen()) {
            this.parent.removeChild(this.host);
            this.parent.removeEventListener('keyup', this, true);
        }
    },
    start: function(config) {
        this.open();
        this.canvas.getContext('2d').fillStyle = config.color;
        if (config.callback)
            this.callback = config.callback;
    },
    stop: function() {
        this.close()
        delete this.callback;
    },
    pulse: function(config) {
        this.animating = true;
        this.canvas.classList.add('pulse');
        this.start(config);
        this.draw(config.coords);
    },
    draw: function(coords) {
        this.clear();
        var context = this.canvas.getContext('2d');
        context.fillRect(coords.x, coords.y, coords.width, coords.height);
    },
    clear: function() {
        var canvas = this.canvas;
        canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height);
    },
    getInstance: function() {
        if (Highlighter._instance == null)
            Highlighter._instance = createBoxWidget();
        return Highlighter._instance;
    },
    handleEvent: function(event) {
        var canvas = this.canvas;

        if (event instanceof WebKitAnimationEvent) {
            this.animating = false;
            canvas.classList.remove('pulse');
            this.close();
            return;
        }

        event.preventDefault();

        if (this.animating)
            return;

        if (event instanceof MouseEvent) {
            if (event.button !== 0)
                return;

            var clientX = event.clientX;
            var clientY = event.clientY;
            var coords = this.coords;

            if (event.type === 'mousemove') {
                coords.update(clientX, clientY);
                this.draw(coords);
                return;
            }

            if (event.type === 'mousedown') {
                coords.setOrigin(clientX, clientY);
                canvas.addEventListener('mousemove', this);
                canvas.addEventListener('mouseup', this);
                return;
            }

            if (event.type === 'mouseup') {
                canvas.removeEventListener('mousemove', this);
                canvas.addEventListener('mouseup', this);
                this.callback(coords);
            }
        }

        if (event instanceof KeyboardEvent) {
            switch (event.keyCode) {
                case 27:
                    this.callback();
            }
        }
    },
    callback: function() {}
};

function BoundingBox() {
    this.width = 0;
    this.height = 0;
}

BoundingBox.prototype.setOrigin = function(x, y) {
    this.x = x;
    this.y = y;
};

BoundingBox.prototype.update = function(dx, dy) {
    this.width = dx - this.x;
    this.height = dy - this.y;
};

function createCanvasElement() {
    var host = document.createElement('div');
    host.style.cssText = 'position:fixed;top:0;left:0;right:0;bottom:0;z-index:2147483645';
    var style = document.createElement('style');
    style.innerText = utils.createShadowStyle('highlighter.css');
    var container = document.createElement('canvas');
    container.className = 'box';
    var shadow = utils.getShadowRoot(host);
    shadow.appendChild(style);
    shadow.appendChild(container);
    return host;
}

function createBoxWidget() {
    var host = createCanvasElement();
    var widget = utils.createWidget(Highlighter, host, document.documentElement);
    var shadow = widget.shadow;
    widget.coords = new BoundingBox();
    widget.canvas = shadow.querySelector('.box');
    widget.canvas.addEventListener('mousedown', widget);
    widget.canvas.addEventListener('webkitAnimationEnd', widget);
    return widget;
}

return {
    Highlighter: Highlighter
};

});
